package fr.labri.harmony.analysis.jsep.results;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class LoadRules {
	
	private static Set<Pair<String,String>> rules=null;
	private static Map<Pair<String,String>, Integer> rules_scores=null;


	private static  List<Set<String>> categories=null;
	
	public static List<Set<String>> getCategories() throws IOException {
		List<Set<String>> toReturn = new ArrayList<Set<String>>();
		List<String> lines = Files.readAllLines(Paths.get("Rules.csv"), Charset.forName("UTF-8"));
		for(String line : lines) {
			String tk[] = line.split("\\;");
			if(tk.length>=4 && tk[3]!=null){
				if(tk[3].equals("true")) {
					int idx = toReturn.size();
					for(int k = 0 ; k < toReturn.size() ; k++) {
						if(toReturn.get(k).contains(tk[0].trim()) || toReturn.get(k).contains(tk[1].trim())) {
							idx=k;					
							break;
						}
					}
					if(idx==toReturn.size()) {
						toReturn.add(idx, new HashSet<String>());
					}
					toReturn.get(idx).add(tk[0].trim());
					toReturn.get(idx).add(tk[1].trim());
				}
			}
		}
		
		List<Set<String>> toRemove = new ArrayList<Set<String>>();
		for(int k = 0 ; k < toReturn.size()-1 ; k++) {
			for(int l = k+1 ; l < toReturn.size() ; l++) {
				if(toReturn.get(k).removeAll(toReturn.get(l))) {
					toRemove.add(toReturn.get(l));
					toReturn.get(k).addAll(toReturn.get(l));
				}
				else if (toReturn.get(l).removeAll(toReturn.get(k))) {
					toRemove.add(toReturn.get(k));			
					toReturn.get(l).addAll(toReturn.get(k));
				}
			}
		}
		toReturn.removeAll(toRemove);
//		for(Set<String> tr : toReturn) {
//			System.out.println(tr);
//		}
		return toReturn;
	}
	
	static Set<Pair<String,String>> getAllTrueRules() throws IOException {
		Set<Pair<String,String>> toReturn = new HashSet<Pair<String,String>>();
		if(categories==null)
			categories = getCategories();
		for(int k = 0 ; k < categories.size()-1 ; k++) {
			List<String> libs = new ArrayList<String>(categories.get(k));
			for(int l = 0 ; l < libs.size()-1 ; l++) {
				for(int m = l+1 ; m < libs.size() ; m++) {
					toReturn.add(new Pair<String, String>(libs.get(l), libs.get(m)));
					toReturn.add(new Pair<String, String>(libs.get(m), libs.get(l)));
				}
			}
		}
		return toReturn;
	}
	
	static Map<Pair<String,String>, Integer> getAllTrueRulesScore() throws IOException {
		Map<Pair<String,String>,Integer> toReturn = new HashMap<Pair<String,String>, Integer>();
		List<String> lines = Files.readAllLines(Paths.get("Rules.csv"), Charset.forName("UTF-8"));
		for(String line : lines) {
			String tk[] = line.split("\\;");
			if(tk.length>=4 && tk[3]!=null)
				if(tk[3].equals("true")) {
					toReturn.put(new Pair<String, String>(tk[0], tk[1]), Integer.valueOf(tk[2]));
				}
		}
		return toReturn;
	}
	
	public static int getRuleCat(String source, String target) throws IOException {
		if(isTrueRule(source,target)==false) 
			return -1;
		
		for(int k = 0 ; k < categories.size()-1 ; k++) {
			List<String> libs = new ArrayList<String>(categories.get(k));
			if(libs.contains(source) && libs.contains(target))
				return k;
		}
		return -1;
	}
	
	public static boolean isTrueRule(String source, String target) throws IOException {
		if(rules==null)
			rules = getAllTrueRules();
		return rules.contains(new Pair<String,String>(source, target));
	}
	
	public static Integer getScore(String source, String target) throws IOException {
		if(rules_scores==null)
			rules_scores = getAllTrueRulesScore();
		return rules_scores.get(new Pair<String,String>(source, target));
	}

	public static Set<String> getLibraries() throws IOException {
		if(rules==null)
			rules = getAllTrueRules();
		Set<String> toReturn = new HashSet<String>();
		for(Set<String> cat : getCategories()) {
			toReturn.addAll(cat);
		}
		return toReturn;
	}

	public static int getInDegree(String library) throws IOException {
		if(rules_scores==null)
			rules_scores = getAllTrueRulesScore();
		int indegree=0;
		for(Pair<String,String> pair : rules_scores.keySet()) {
			if(pair.getElement1().equals(library))
				indegree+=rules_scores.get(pair);
		}
		return indegree;
	}
	
	public static int getOutDegree(String library) throws IOException {
		if(rules_scores==null)
			rules_scores = getAllTrueRulesScore();
		int outdegree=0;
		for(Pair<String,String> pair : rules_scores.keySet()) {
			if(pair.getElement0().equals(library))
				outdegree+=rules_scores.get(pair);
		}
		return outdegree;
	}

}
